/**
 *  Copyright 2009 Henning Teek, Ingo Renner
 *  
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  
 *  http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License. 
 */
package com.googlecode.chigscommons.repository.jpa.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Hex;
import org.apache.log4j.lf5.util.StreamUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.googlecode.chigscommons.repository.StorehouseService;
import com.googlecode.chigscommons.repository.UncheckedRuntimeException;

/**
 * @author Ingo Renner
 * @author Henning Teek
 */
@Service("storehouseService")
public class StorehouseServiceImpl implements StorehouseService {
	private final static Logger log = LoggerFactory.getLogger(StorehouseServiceImpl.class);

	@Override
	public File getDataFile(String digest) {
		if (digest == null) {
			throw new UncheckedRuntimeException("Fatal error: digest must not be null.");
		}
		return new File(getDataDir(), digest);
	}

	private File getDataDir() {
		final File storehouse = new File("target/storehouse");
		if (!storehouse.exists()) {
			storehouse.mkdirs();
		}
		return storehouse;
	}

	@Override
	public String doImport(InputStream inputStream, byte[] md5sum) {
		try {
			final String digest = toHexString(md5sum);
			// TODO check for existing data with same digest
			File data = getDataFile(digest);
			if( data.exists() ) {
				data.delete();
				log.info("Data already exists, it will be replaced.");
			}
			createFile(data);
			OutputStream outputStream = new FileOutputStream(data);
			StreamUtils.copyThenClose(inputStream, outputStream);
			log.info("saved file: " + digest);
			return digest;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public File createFile(File file) throws IOException {
		if( file.getParentFile()!= null && !file.getParentFile().exists() ) {
			file.getParentFile().mkdirs(); 
		}
		file.createNewFile();
		return file;
	}

	private String toHexString(byte[] md5hashAsByteArray) {
		final Hex hex = new Hex();
		return new String(hex.encode(md5hashAsByteArray)); 
	}

	@Override
	public String createMD5Digest(String filename) throws IOException {
		InputStream fis =  new FileInputStream(filename);
		byte[] buffer = new byte[1024];
		MessageDigest complete;
		try {
			complete = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			throw new UncheckedRuntimeException(e);
		}
		int numRead;
		do {
			numRead = fis.read(buffer);
			if (numRead > 0) {
				complete.update(buffer, 0, numRead);
			}
		} while (numRead != -1);
		fis.close();
		return toHexString(complete.digest());
	}
}
